/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package it.polimi.registration.business.security.boundary;


import it.polimi.registration.business.security.entity.Friend;
import it.polimi.registration.business.security.entity.Group;
import it.polimi.registration.business.security.entity.GroupFriend;
import it.polimi.registration.business.security.entity.Invite;
import it.polimi.registration.business.security.entity.User;
import static java.lang.Boolean.FALSE;
import static java.lang.Boolean.TRUE;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.ValidatorFactory;
import javax.enterprise.event.Event;
import javax.persistence.NoResultException;





/**
 *
 * @author miglie
 */

@Stateless
public class UserManager {

    @PersistenceContext
    EntityManager em;
    
    @Inject
    Principal principal;
    
    @Inject
    private Event<User> UserDeleteEvent;
    
    
    private Object JsfUtil;
    private GroupFriend gf;

    public void save(User user) 
    {
        user.setGroupName(Group.USERS);
        em.persist(user);
        gf=new GroupFriend("lista_amici",user);
        em.persist(gf);
    }
    
    
public void delete(User user)
    {
        TypedQuery<User> query = em.createQuery("SELECT e FROM User e Where e.email = :id", User.class);
             query.setParameter("id",user.getEmail());
            User lista;
            lista= query.getSingleResult();
        String a,b,c;
        a=user.getEmail();
        b=user.getName();
        c=user.getSurname();
        System.out.println("elimino utente "+b+c+a);
        UserDeleteEvent.fire(lista);
        em.remove(lista);
    }


    public void unregister(){
        User user = getLoggedUser();
        for(it.polimi.registration.business.security.entity.Event event: user.getEventCollection()){
            for (Invite invite : event.getInviteCollection()){
                em.remove(invite);
                em.flush();
            }
            
            for (it.polimi.registration.business.security.entity.SystemNotification sn : event.getSystemNotificationCollection()){
                em.remove(sn);
                em.flush();
            }
            
            em.refresh(event);
            em.remove(event);
        }

        for(it.polimi.registration.business.security.entity.GroupFriend groupFriend: user.getGroupLabelCollection()){
            em.remove(groupFriend);
            em.flush();
        }
        for(it.polimi.registration.business.security.entity.Invite invite: user.getInviteCollection()){
            em.remove(invite);
            em.flush();
        }
        for(it.polimi.registration.business.security.entity.SystemNotification sn: user.getSystemNotificationCollection()){
            em.remove(sn);
            em.flush();
        }
        
        for(it.polimi.registration.business.security.entity.Friend receiver: user.getFriendshipNotificationReceiver()){
            em.remove(receiver);
            em.flush();
        }
        
        for(it.polimi.registration.business.security.entity.Friend sender: user.getFriendshipNotificationSender()){
            em.remove(sender);
            em.flush();
        }
        
        em.refresh(getLoggedUser());
        em.remove(getLoggedUser());
    }

    public User getLoggedUser() {
        return em.find(User.class, principal.getName());
    }
    
    public void update(User user) {
        em.merge(user);
    }
    
    public User search(User user){
        return em.find(User.class, user.getEmail());
    }
    
    public void create(User entity) {
        
        if(em==null)
         {System.out.println("em da creare!!!");}

    ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        javax.validation.Validator validator = factory.getValidator();
    Set<ConstraintViolation<User>> constraintViolations = validator.validate(entity);
    if(constraintViolations.size() > 0){
        Iterator<ConstraintViolation<User>> iterator = constraintViolations.iterator();
        while(iterator.hasNext()){
            ConstraintViolation<User> cv = iterator.next();
            System.err.println(cv.getRootBeanClass().getName()+"."+cv.getPropertyPath() + " " +cv.getMessage());

         //   JsfUtil.addErrorMessage(cv.getRootBeanClass().getSimpleName()+"."+cv.getPropertyPath() + " " +cv.getMessage());
        }
    }else{
        em.persist(entity);
    }
    }
    
    public List<User> findAllUser(){
        User u = this.getLoggedUser();
        TypedQuery<User> query = em.createQuery("SELECT u FROM User u Where u.email != :mail", User.class).setParameter("mail", em.find(User.class, u.getEmail()).getEmail());
    return query.getResultList();
    }
    
    public User getUser(String mail) {
        return em.find(User.class, mail);
    }
    
    
     /**
     *
     * @param u1
     * @param u2
     * @return the integer indicate if there is a request between the two user 
     * the integer distinguished the verse 1 indicate sender to receiver 2 receiver to sender and 0 no request between they
     */
    public int Relationshipcheck(User u1,User u2)
  {
    TypedQuery<Friend> query = em.createQuery("SELECT e FROM Friend e Where e.sender = :sender AND e.receiver = :receiver AND e.unread =:unread", Friend.class);
        query.setParameter("sender",u1);
        query.setParameter("receiver",u2);
        query.setParameter("unread",TRUE);
        Friend gg=null;
        try
        {
           gg = query.getSingleResult();
           //System.out.println("prima query:ricevo sender: "+gg.getSender().getName()+"receiver: "+gg.getReceiver().getName());
        }
        catch (NoResultException nre)
        {
           // System.out.println("prima eccezione non ho trovato la query richiesta tra "+sender.getName()+receiver.getName());
        }
        
    if(gg==null)
    {
        return 0;
    }
    return 1;
      
  }
    
  public boolean isFriend(User u1)
  {
    
    TypedQuery<User> query2 = em.createQuery("SELECT e FROM User e Where e.email = :id", User.class);
        query2.setParameter("id",u1.getEmail());
        User amico;
        amico= query2.getSingleResult();
        
    User local=getLoggedUser();
    TypedQuery<GroupFriend> query = em.createQuery("SELECT e FROM GroupFriend e Where e.owner = :mail", GroupFriend.class);
            query.setParameter("mail",local);
            List <GroupFriend> gf;
            gf = query.getResultList(); //non faccio try catch perchè un gruppo c'è sempre il gruppo lista_amici il gruppo default
    int i;
    GroupFriend ff;
    for(i=0;i<gf.size();i++)
    {
        ff= gf.get(i);
        System.out.println("ho trovato il gruppo: "+ff.getName()+"con dentro:"+ff.toString());
        if(ff.isIntheList(amico))
        {
            return TRUE;
        }
       System.out.println("gruppo: "+ff.getName()+" controllato utente: "+ u1.getName()+" non presente"); 
    }
    return FALSE;
  }
    
}
